#include "gcode_control.h"
#include "gcode.h"
#include "file.h"
#include "display.h"
#include <string.h>
#include "screen_io.h"
#include "screen_font.h"
#include "parse.h"
#include "delay.h"
#include "interrupt.h"
#include "keyboard.h"
#include "rte_rtc.h"
#include "ili9320.h"
#include "rs232_interface.h"

const MenuStructST MainMenu[] =
{
    {START_GCODE, "-> Start Gcode"},
    {MANUAL_MODE, "-> Manual Mode"},
    {SHOW_GCODE, "-> Show Gcode"},
    {FILE_SYSTEM, "-> File System"},
    {SET_TIME, "-> Set Time"},
    {SCAN_MODE, "-> Scan Mode"},
    {PARAM_SET, "-> Start Gcode"},
    {TOUCH_SET, "-> Start Gcode"},
    {STEPMOTOR_TEST, "-> Stepmotor Test"},
    {NULL}
};

/***************************************************
 *  Show status
 ***************************************************/
void showStatusString(void)
{
    static uint8_t limits = 0;
    char time[10];
    char temp[10];
    struct tm rtc;
    // Display every second
    win_showWindow(0, LCD_HEIGHT - (FONT_STEP_Y + BORDER_PADDING * 2), 50, 1, Yellow, Yellow, Black);
    //        scr_Rectangle(0, 210, LCD_WIDTH, LCD_HEIGHT, Yellow, true);
    //        scr_gotoxy(2, 0);
    scr_fontColor(Black, Yellow);
    rtc_gettime(&rtc);
    sprintf(time, "%02d:%02d:%02d ", rtc.tm_hour, rtc.tm_min, rtc.tm_sec);
    scr_putsat(&time[0], 2, TEXT_Y_MAX);
    scr_fontColor(_smParam.maxExtrudeTemperature > extrudT_getTemperatureReal() ? Green : Red, Yellow);
    sprintf(temp, "t:%dC", extrudT_getTemperatureReal());
    scr_putsat(temp, 20, TEXT_Y_MAX);

    scr_clrEndl();
    //    sec = Seconds();
    limits = 0xFF;

    if (limits != limits_chk())
    {
        limits = limits_chk();
        scr_Rectangle(280, 220, 290, 235, limitX_chk() ? Red : Green, true);
        scr_Rectangle(293, 220, 303, 235, limitY_chk() ? Red : Green, true);
        scr_Rectangle(306, 220, 316, 235, limitZ_chk() ? Red : Green, true);
    }
}

/***************************************************
 *  Show critical status
 ***************************************************/
void showCriticalStatus(char* msg, int st)
{
    win_showErrorWin();
    scr_gotoxy(2, 2);
    scr_printf(msg, st);
    WAIT_KEY_C();
}


/***************************************************
 *  Show critical status
 ***************************************************/
void showNonCriticalStatus(char* msg, int st)
{
    win_showErrorWin();
    scr_gotoxy(2, 2);
    scr_printf(msg, st);
    WAIT_KEY_C();
}

uint8_t questionYesNo(char* msg, char* param)
{
    win_showMsgWin();
    scr_printf(msg, param);
    scr_gotoxy(3, 6);
    scr_puts("\n -Cancle[L]  -Yes   [R]");
    //    SetTouchKeys(kbdQuestion);
    switch (kbd_GetKey())
    {
    case KEY_R_DOWN:
        return 1;
    case KEY_L_DOWN:
        return 0;
    default:
        break;
    }
    return 0;
}

void limit_val(int* a, int max, int min)
{
    if (*a > max)
        * a = max;
    if (*a < min)
        * a = min;
}

void roll_val(int* a, int max, int min)
{
    if (*a > max)
        * a = min;
    if (*a < min)
        * a = max;
}

void SetTime(void)
{
    struct tm rtc;
    int c = -1, pos = 0, v = 0;

    win_showMsgWin();
    scr_setScroll(false);
    rtc_gettime(&rtc);
    scr_puts("\n -Left  [L]  -Right [R]");
    scr_puts("\n -Up    [U]  -Down  [D]");
    scr_puts("\n -OK    [C]");
    do
    {
        if (c == KEY_L_DOWN) pos = pos <= 0 ? 5 : pos - 1;
        if (c == KEY_R_DOWN) pos = pos >= 5 ? 0 : pos + 1;

        switch (pos)
        {
        case 0:
            v = rtc.tm_mon;
            break;
        case 1:
            v = rtc.tm_mday;
            break;
        case 2:
            v = rtc.tm_year;
            break;
        case 3:
            v = rtc.tm_hour;
            break;
        case 4:
            v = rtc.tm_min;
            break;
        case 5:
            v = rtc.tm_sec;
            break;
        }
        DBG_DEBUG("val:%d--pos:%d", v, pos);


        scr_gotoxy(0, 5);
        scr_fontColorNormal();
        scr_printf(" New: %02d/%02d/%04d %02d:%02d:%02d", rtc.tm_mon, rtc.tm_mday, rtc.tm_year, rtc.tm_hour, rtc.tm_min, rtc.tm_sec);
        scr_fontColorInvers();
        if (pos > 2)
        {
            scr_gotoxy(pos * 3 + 8, 5);
        }
        else
        {
            scr_gotoxy(pos * 3 + 6, 3);
        }
        if (pos == 2)
        {
            scr_printf("%04d", v);
        }
        else
        {
            scr_printf("%02d", v);
        }


        c = kbd_GetKey();

        if (c == KEY_U_DOWN) v++;
        if (c == KEY_D_DOWN) v--;
        switch (pos)
        {
        case 0:
            limit_val(&v, 12, 1);
            rtc.tm_mon = v;
            break;
        case 1:
            limit_val(&v, 31, 1);
            rtc.tm_mday = v;
            break;
        case 2:
            limit_val(&v, 2030, 2000);
            rtc.tm_year = v;
            break;
        case 3:
            limit_val(&v, 23, 0);
            rtc.tm_hour = v;
            break;
        case 4:
            limit_val(&v, 59, 0);
            rtc.tm_min = v;
            break;
        case 5:
            limit_val(&v, 59, 0);
            rtc.tm_sec = v;
            break;
        }
    } while (c != KEY_C_DOWN);
    if (questionYesNo("Save", " Settings?"))
    {
        rtc.tm_mon--;
        rtc_settime(&rtc);
    }

}


void ShowFileInfo(void)
{
    FRESULT fres;
    FILINFO finf;
    int c, n;

    memset(&finf, 0, sizeof(finf));

    win_showMsgWin();
    scr_setScroll(false);
    scr_printf("File:%s", fileList[currentFile].f_name);
    f_stat(fileList[currentFile].f_name, &finf);
    scr_gotoxy(0, 1);
    scr_printf("Size:%d\n", (uint32_t)finf.fsize);

    fres = f_open(&fid, fileList[currentFile].f_name, FA_READ);
    if (fres != FR_OK)
    {
        scr_printf("Error open file: '%s'\nStatus:%d [%d]", fileList[currentFile].f_name, fres);
    }
    else
    {
        char str[150];
        scr_fontColorInvers();
        scr_setScroll(false);
        // Read lines from 3 to 6 from file and display it
        for (n = 2; n < 7 && f_gets(str, sizeof(str), &fid) != NULL; n++)
        {
            scr_gotoxy(0, n);
            scr_puts(str_trim(str));
        }
    }
    scr_fontColorNormal();
    scr_gotoxy(8, 7);
    scr_printf("PRESS C-KEY");
    do
    {
        c = kbd_GetKey();
        if (c == KEY_R_DOWN)
        {
            char str[150];
            scr_fontColorInvers();
            for (n = 2; n < 7 && f_gets(str, sizeof(str), &fid) != NULL; n++)
            {
                scr_gotoxy(0, n);
                scr_puts(str_trim(str));
                scr_clrEndl();
            }
        }
    } while (c != KEY_C_DOWN);
    f_close(&fid);

}


uint8_t ShowMenu(char* tittle, int menuNum, const MenuStructST menuList[])
{
    int8_t pos = 0;
    KEY_ENUM c;

    LCD_Clear(Black);
    win_showMenu(0, 50, 40, 13, tittle);

    do
    {
        c = kbd_GetKey();
        if (c == KEY_U_DOWN) pos = pos <= 0 ? (menuNum - 1) : pos - 1;
        if (c == KEY_D_DOWN) pos = pos >= (menuNum - 1) ? 0 : pos + 1;

        scr_gotoxy(0, 0);
        for (int i = 0; i < menuNum; i++)
        {
            if (i == pos)
                scr_fontColorInvers();
            else
                scr_fontColorNormal();
            scr_printf("%s\n", &menuList[i].MenuName);
        }

        delay_ms(10);
    } while (c != KEY_R_DOWN);
    return pos;
}


uint8_t ShowSetMenu(char* tittle, int menuNum, char menuList[][MAX_FILE_NAME_SZ], uint32_t valueList[])
{
    int8_t pos = 0;
    uint8_t lastpos = 0;
    uint8_t startP;
    KEY_ENUM c;
    uint8_t valueChanged = 0;
    LCD_Clear(Black);
    startP = 0;
    win_showMenu(0, 50, 40, 13, tittle);
    do
    {
        if (c == KEY_D_DOWN) pos = pos <= 0 ? (menuNum - 1) : pos - 1;
        if (c == KEY_U_DOWN) pos = pos >= (menuNum - 1) ? 0 : pos + 1;
        if (c == KEY_L_DOWN)
        {
            valueChanged = 1;
            valueList[pos]--;
        }
        if (c == KEY_R_DOWN)
        {
            valueChanged = 1;
            valueList[pos]++;
        }
        if (pos >= MAXMENULIST && pos > lastpos)
        {
            startP = (pos - MAXMENULIST) + 1;
        }
        if (startP - pos > 0 && pos < lastpos)
        {
            startP = pos;
        }
        lastpos = pos;
        DBG_DEBUG("startP:%d...pos:%d", startP, pos);

        scr_gotoxy(0, 0);
        for (int i = startP; i < startP + MAXMENULIST; i++)
        {
            if (i == pos)
                scr_fontColorInvers();
            else
                scr_fontColorNormal();
            scr_printf("%s", &menuList[i][0]);
            scr_clrEndl();
            scr_gotoxy(25, i - startP);
            scr_printf("< ");
            scr_printf("%6d", valueList[i]);
            scr_printf(" >\n");
        }
        c = kbd_GetKey();
        delay_ms(10);
    } while (c != KEY_C_DOWN);

    return valueChanged;
}

/***************************************************
*   显示Gcode运行错误状态
****************************************************/
void ShowGcodeErrorStare(uint8_t st, int lineNum, char* str)
{
    scr_fontColor(Red, Black);
    scr_gotoxy(1, 11);
    switch (st)
    {
    case GCSTATUS_BAD_NUMBER_FORMAT:
        scr_puts("BAD_NUMBER_FORMAT");
        break;
    case GCSTATUS_EXPECTED_COMMAND_LETTER:
        scr_puts("EXPECTED_COMMAND_LETTER");
        break;
    case GCSTATUS_UNSUPPORTED_STATEMENT:
        scr_puts("UNSUPPORTED_STATEMENT");
        break;
    case GCSTATUS_FLOATING_POINT_ERROR:
        scr_puts("FLOATING_POINT_ERROR");
        break;
    case GCSTATUS_UNSUPPORTED_PARAM:
        scr_puts("UNSUPPORTED_PARAM");
        break;
    case GCSTATUS_UNSOPORTED_FEEDRATE:
        scr_puts("GCSTATUS_UNSUPPORTED_FEEDRATE");
        break;
    case GCSTATUS_TABLE_SIZE_OVER_X:
        scr_puts("GCSTATUS_TABLE_SIZE_OVER_X");
        break;
    case GCSTATUS_TABLE_SIZE_OVER_Y:
        scr_puts("GCSTATUS_TABLE_SIZE_OVER_Y");
        break;
    case GCSTATUS_TABLE_SIZE_OVER_Z:
        scr_puts("GCSTATUS_TABLE_SIZE_OVER_Z");
        break;
    case GCSTATUS_CANCELED:
        scr_puts("GCSTATUS_CANCELED");
        break;
    }
    scr_printf(" at line %d:\n %s", lineNum, str);
}

/***************************************************
*   显示Gcode运行状态信息
****************************************************/
void ShowGcodeExeState(void)
{
    static uint32_t time;
    int n;
    int i;
    uint32_t t;
    GCODE_CMD* gp;

    // 显示打印进度
    scr_fontColor(Blue, Cyan);
    scr_gotoxy(1, 3);
    scr_printf("SOP:%d/%d(%d%%)", gc.curfsize, gc.totalfsize, gc.curfsize * 100 / gc.totalfsize); //显示打印进度
    win_showProgressBar(15, 100, 200, 16, gc.curfsize * 100 / gc.totalfsize); //显示进度条
    // 显示剩余步数
    scr_gotoxy(0, 8);
    scr_printf(" Remain Moves: %d", stepm_getRemainLines());
    scr_clrEndl();
    // 显示工作时间		
    scr_gotoxy(0, 9);
    time = Seconds();
    t = time - startWorkTime;
    scr_printf(" Work Time: %02d:%02d:%02d", t / 3600, (t / 60) % 60, t % 60);
    scr_clrEndl();

    // 显示当前位置
//    for (i = 0; i < STEPS_MOTORS; i++)
//    {
//        int32_t globalSteps = stepm_getCurGlobalStepsNum(i);
//        double n = (double)globalSteps / axisK[i];
//        scr_gotoxy(1 + i * 10, 6);
//        scr_printf("%c:%f ", axisName[i], n);
//    }

    //	if(stepm_getRemainLines() > 1) {
    /*显示当前正在打印的G代码*/
    for (i = 0; i < MAX_SHOW_GCODE_LINES; i++, n++)
    {
        //        n = lbuf.gcodePtrCur + 1;
        if (n > (MAX_SHOW_GCODE_LINES - 1))
        {
            n = 0;
        }
        gp = &lbuf.gcode[n];
        scr_gotoxy(1, i);
        if (gp->lineNum)
        {
            scr_printf("L[%d]:%s", gp->lineNum, gp->cmd);
        }
        scr_clrEndl();
    }
    //	}
}

uint16_t calcColor(uint8_t val)
{
    if (val < 12) return (uint16_t)0xFFFF - (val << 6);
    if (val < 20) return (uint16_t)0xF81F - ((val - 12) << 12);
    if (val < 32) return (uint16_t)0x047F + ((val - 20) << 6);
    if (val < 40) return (uint16_t)0x07FF - ((val - 32) << 2);
    if (val < 48) return (uint16_t)0x1F70 + ((val - 40) << 13);
    if (val < 64) return (uint16_t)0xFF00 - ((val - 48) << 6);
    return 0x80F0;
}



